# -*- coding: utf-8 -*-
import hashlib
from collections import OrderedDict

import requests
from django.conf import settings

from async import async_job
from common.order import db as order_db
from common.order.model import PAY_STATUS
from common.utils import track_logging
from common.utils.exceptions import ParamError

_LOGGER = track_logging.getLogger(__name__)

APP_CONF = {
    '7355': {
        'API_KEY': '9e14dd7c2295736888efe1367e4e806e',
        'gateway': 'http://pay.changfpay.com/pay.aspx?userid={}&orderid={}&money={}&url={}&aurl={}&bankid={}&sign={}&sign2={}',
        'query_gateway': 'http://pay.changfpay.com/query.aspx?userid={}&orderid={}&sign={}',
    },
    '7915': {
        'API_KEY': 'e85510722f0fde4adb1db02edec166e6',
        'gateway': 'http://pay.changfpay.com/pay.aspx?userid={}&orderid={}&money={}&url={}&aurl={}&bankid={}&sign={}&sign2={}',
        'query_gateway': 'http://pay.changfpay.com/query.aspx?userid={}&orderid={}&sign={}',
    },
    '3351': {
        'API_KEY': '5eeff17788d64f4d8c14b3f3d0927d23',
        'gateway': 'http://api.pinzujia.com/pay.aspx?userid={}&orderid={}&money={}&url={}&aurl={}&bankid={}&sign={}&sign2={}',
        'query_gateway': 'api.pinzujia.com/query.aspx?userid={}&orderid={}&sign={}',
    },
    '7971': {
        'API_KEY': '511b0809c8eafbcd0a41935b8c7d3cbb',
        'gateway': 'http://pay.changfpay.com/pay.aspx?userid={}&orderid={}&money={}&url={}&aurl={}&bankid={}&sign={}&sign2={}',
        'query_gateway': 'http://pay.changfpay.com/query.aspx?userid={}&orderid={}&sign={}',
    },
    '3410': {  # loki 支付方式，费率，单笔限额：qq和京东是1.8%单笔都是0---5000，支付宝3.5%单笔0---5000。都是do结算。微信2.5%单笔不限额是d1结算。
        'API_KEY': 'c6308465991140829ed7b08a807a6f91',
        'gateway': 'http://api.boha1.com/pay.aspx?userid={}&orderid={}&money={}&url={}&aurl={}&bankid={}&sign={}&sign2={}',
        'query_gateway': 'http://api.boha1.com/query.aspx?userid={}&orderid={}&sign={}',
    },
}


def _get_api_key(mch_id):
    return APP_CONF[mch_id]['API_KEY']


def _get_gateway(mch_id):
    return APP_CONF[mch_id]['gateway']


def _get_query_gateway(mch_id):
    return APP_CONF[mch_id]['query_gateway']


def generate_charge_sign(parameter, key):
    '''  生成下单签名 '''
    s = 'userid={}&orderid={}&bankid={}&keyvalue={}'.format(
        parameter['userid'], parameter['orderid'], parameter['bankid'],
        key)
    m = hashlib.md5()
    m.update(s.encode('utf8'))
    sign = m.hexdigest()
    s2 = 'money={}&userid={}&orderid={}&bankid={}&keyvalue={}'.format(
        parameter['money'], parameter['userid'], parameter['orderid'],
        parameter['bankid'], key)
    m2 = hashlib.md5()
    m2.update(s2.encode('utf8'))
    sign2 = m2.hexdigest()
    _LOGGER.info(u'origin string: %s, sign:%s, sign2:%s', s, sign, sign2)
    return sign, sign2


# 微信	2001
# 支付宝	2003
# 微信WAP	2005
# 支付宝WAP	2007
# QQ扫码	2008
# QQWAP	2009
# 京东钱包	2010
# 京东钱包WAP	2011
# 银联钱包	2012
def _get_pay_type(service):
    if service == 'alipay':
        return '2007'
    elif service == 'union':
        return '2012'
    elif service == 'qq':
        return '2009'
    elif service == 'jd':
        return '2011'
    else:
        return '2005'  # wx


# QQ钱包BANKID=2008   QQ钱包wap=2009
def create_charge(pay, pay_amount, info):
    ''' 创建订单 '''
    charge_resp = {}
    app_id = info['app_id']
    api_key = _get_api_key(app_id)
    service = info.get('service')  # wechat or alipay
    p_dict = OrderedDict((
        ('userid', app_id),
        ('orderid', pay.id),
        ('money', pay_amount),
        ('url', '{}/pay/api/{}/changfu/'.format(settings.NOTIFY_PREFIX, settings.NOTIFY_PATH)),
        ('aurl', '{}/pay/api/{}/changfu/{}/'.format(
            settings.NOTIFY_PREFIX, settings.RETURN_PATH, pay.id)),
        ('bankid', _get_pay_type(service)),
    ))
    p_dict['sign'], p_dict['sign2'] = generate_charge_sign(p_dict, api_key)
    gate_url = _get_gateway(app_id).format(p_dict['userid'], p_dict['orderid'], p_dict['money'],
                                           p_dict['url'], p_dict['aurl'], p_dict['bankid'], p_dict['sign'],
                                           p_dict['sign2'])
    _LOGGER.info('changfupay brefore data: %s', gate_url)
    charge_resp.update({
        'charge_info': gate_url
    })
    return charge_resp


def verify_notify_sign(parameter, key):
    '''验证通知签名 '''
    s = 'returncode={}&userid={}&orderid={}&keyvalue={}'.format(
        parameter['returncode'], parameter['userid'], parameter['orderid'],
        key)
    m = hashlib.md5()
    m.update(s.encode('utf8'))
    sign = m.hexdigest()
    s2 = 'money={}&returncode={}&userid={}&orderid={}&keyvalue={}'.format(
        parameter['money'], parameter['returncode'], parameter['userid'],
        parameter['orderid'], key)
    m2 = hashlib.md5()
    m2.update(s2.encode('utf8'))
    sign2 = m2.hexdigest()
    if sign != parameter['sign']:
        _LOGGER.info("changfu sign: %s, calculated sign: %",
                     parameter['sign'], sign)
        raise ParamError('sign not pass, data: %s' % parameter)
    if sign2 != parameter['sign2']:
        _LOGGER.info("changfu sign2: %s, calculated sign2: %",
                     parameter['sign2'], sign2)
        raise ParamError('sign2 not pass, data: %s' % parameter)
    return sign, sign2


def check_notify_sign(request):
    data = dict(request.GET.iteritems())
    _LOGGER.info("changfu notify data: %s", data)
    app_id = data.get('userid')
    api_key = _get_api_key(app_id)
    verify_notify_sign(data, api_key)
    pay_id = data['orderid']
    if not pay_id:
        _LOGGER.error("fatal error, orderid not exists, data: %s" % data)
        raise ParamError('changfu event does not contain pay ID')

    pay = order_db.get_pay(int(pay_id))
    if not pay:
        raise ParamError('pay_id: %s invalid' % pay_id)
    if pay.status != PAY_STATUS.READY:
        raise ParamError('pay %s has been processed' % pay_id)

    trade_status = int(data['returncode'])
    mch_id = pay.mch_id
    trade_no = data['orderid']
    total_fee = float(data['money'])

    extend = {
        'trade_status': trade_status,
        'trade_no': trade_no,
        'total_fee': total_fee
    }

    from common.channel.pay import check_channel_order
    check_channel_order(pay_id, total_fee, app_id)

    if trade_status == 1:
        _LOGGER.info('changfu check order success, mch_id:%s pay_id:%s' % (mch_id, pay_id))
        order_db.add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
        # async notify
        async_job.notify_mch(pay_id)


def _get_query_sign(d, key):
    s = 'userid={}&orderid={}&keyvalue={}'.format(d['userid'], d['orderid'], key)
    m = hashlib.md5()
    m.update(s.encode('utf8'))
    return m.hexdigest().lower()


def _get_str(s, start, end):
    p1 = s.index(start)
    p2 = s.index(end, p1 + len(start))
    if p2 > p1:
        return s[p1 + len(start): p2]
    else:
        return ''


def query_charge(pay_order, app_id):
    ''' 查询订单 '''
    pay_id = pay_order.id
    key = _get_api_key(app_id)
    parameter_dict = OrderedDict((
        ("userid", app_id),
        ("orderid", pay_id),
    ))
    parameter_dict['sign'] = _get_query_sign(parameter_dict, key)
    url = _get_query_gateway(app_id).format(parameter_dict['userid'], parameter_dict['orderid'], parameter_dict['sign'])
    response = requests.get(url)
    _LOGGER.info(u'changfu query: %s', response.text)
    if response.status_code == 200:
        trade_status = _get_str(response.text, 'returncode=', '&')  # 0 订单未成功 1订单成功
        total_fee = float(_get_str(response.text, 'paymoney=', '&'))
        trade_no = ''
        extend = {
            'trade_status': trade_status,
            'trade_no': trade_no,
            'total_fee': total_fee
        }

        if trade_status == '1':
            _LOGGER.info('changfu query order success, mch_id:%s pay_id:%s' % (pay_order.mch_id, pay_id))
            order_db.add_pay_success(pay_order.mch_id, pay_id, total_fee, trade_no, extend)
            async_job.notify_mch(pay_order.id)
    else:
        _LOGGER.warn('changfu data error, status_code: %s', response.status_code)
